home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / sfnt / ttcmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  39.4 KB  |  1,100 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttcmap.c                                                               */
  4. /*                                                                         */
  5. /*    TrueType character mapping table (cmap) support (body).              */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_DEBUG_H
  21. #include "ttload.h"
  22. #include "ttcmap.h"
  23.  
  24. #include "sferrors.h"
  25.  
  26.  
  27.   /*************************************************************************/
  28.   /*                                                                       */
  29.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  30.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  31.   /* messages during execution.                                            */
  32.   /*                                                                       */
  33. #undef  FT_COMPONENT
  34. #define FT_COMPONENT  trace_ttcmap
  35.  
  36.  
  37.   FT_CALLBACK_DEF( FT_UInt )
  38.   code_to_index0( TT_CMapTable*  charmap,
  39.                   FT_ULong       char_code );
  40.  
  41.   FT_CALLBACK_DEF( FT_ULong )
  42.   code_to_next0( TT_CMapTable*  charmap,
  43.                  FT_ULong       char_code );
  44.  
  45.   FT_CALLBACK_DEF( FT_UInt )
  46.   code_to_index2( TT_CMapTable*  charmap,
  47.                   FT_ULong       char_code );
  48.  
  49.   FT_CALLBACK_DEF( FT_ULong )
  50.   code_to_next2( TT_CMapTable*  charmap,
  51.                  FT_ULong       char_code );
  52.  
  53.   FT_CALLBACK_DEF( FT_UInt )
  54.   code_to_index4( TT_CMapTable*  charmap,
  55.                   FT_ULong       char_code );
  56.  
  57.   FT_CALLBACK_DEF( FT_ULong )
  58.   code_to_next4( TT_CMapTable*  charmap,
  59.                  FT_ULong       char_code );
  60.  
  61.   FT_CALLBACK_DEF( FT_UInt )
  62.   code_to_index6( TT_CMapTable*  charmap,
  63.                   FT_ULong       char_code );
  64.  
  65.   FT_CALLBACK_DEF( FT_ULong )
  66.   code_to_next6( TT_CMapTable*  charmap,
  67.                  FT_ULong       char_code );
  68.  
  69.   FT_CALLBACK_DEF( FT_UInt )
  70.   code_to_index8_12( TT_CMapTable*  charmap,
  71.                      FT_ULong       char_code );
  72.  
  73.   FT_CALLBACK_DEF( FT_ULong )
  74.   code_to_next8_12( TT_CMapTable*  charmap,
  75.                     FT_ULong       char_code );
  76.  
  77.   FT_CALLBACK_DEF( FT_UInt )
  78.   code_to_index10( TT_CMapTable*  charmap,
  79.                    FT_ULong       char_code );
  80.  
  81.   FT_CALLBACK_DEF( FT_ULong )
  82.   code_to_next10( TT_CMapTable*  charmap,
  83.                   FT_ULong       char_code );
  84.  
  85.  
  86.   /*************************************************************************/
  87.   /*                                                                       */
  88.   /* <Function>                                                            */
  89.   /*    TT_CharMap_Load                                                    */
  90.   /*                                                                       */
  91.   /* <Description>                                                         */
  92.   /*    Loads a given TrueType character map into memory.                  */
  93.   /*                                                                       */
  94.   /* <Input>                                                               */
  95.   /*    face   :: A handle to the parent face object.                      */
  96.   /*    stream :: A handle to the current stream object.                   */
  97.   /*                                                                       */
  98.   /* <InOut>                                                               */
  99.   /*    table  :: A pointer to a cmap object.                              */
  100.   /*                                                                       */
  101.   /* <Return>                                                              */
  102.   /*    FreeType error code.  0 means success.                             */
  103.   /*                                                                       */
  104.   /* <Note>                                                                */
  105.   /*    The function assumes that the stream is already in use (i.e.,      */
  106.   /*    opened).  In case of error, all partially allocated tables are     */
  107.   /*    released.                                                          */
  108.   /*                                                                       */
  109.   FT_LOCAL_DEF FT_Error
  110.   TT_CharMap_Load( TT_Face        face,
  111.                    TT_CMapTable*  cmap,
  112.                    FT_Stream      stream )
  113.   {
  114.     FT_Error      error;
  115.     FT_Memory     memory;
  116.     FT_UShort     num_SH, num_Seg, i;
  117.     FT_ULong      j, n;
  118.  
  119.     FT_UShort     u, l;
  120.  
  121.     TT_CMap0*     cmap0;
  122.     TT_CMap2*     cmap2;
  123.     TT_CMap4*     cmap4;
  124.     TT_CMap6*     cmap6;
  125.     TT_CMap8_12*  cmap8_12;
  126.     TT_CMap10*    cmap10;
  127.  
  128.     TT_CMap2SubHeader*  cmap2sub;
  129.     TT_CMap4Segment*    segments;
  130.     TT_CMapGroup*       groups;
  131.  
  132.  
  133.     if ( cmap->loaded )
  134.       return SFNT_Err_Ok;
  135.  
  136.     memory = stream->memory;
  137.  
  138.     if ( FILE_Seek( cmap->offset ) )
  139.       return error;
  140.  
  141.     switch ( cmap->format )
  142.     {
  143.     case 0:
  144.       cmap0 = &cmap->c.cmap0;
  145.  
  146.       if ( READ_UShort( cmap0->language )         ||
  147.            ALLOC( cmap0->glyphIdArray, 256L )     ||
  148.            FILE_Read( cmap0->glyphIdArray, 256L ) )
  149.         goto Fail;
  150.  
  151.       cmap->get_index = code_to_index0;
  152.       cmap->get_next_char = code_to_next0;
  153.       break;
  154.  
  155.     case 2:
  156.       num_SH = 0;
  157.       cmap2  = &cmap->c.cmap2;
  158.  
  159.       /* allocate subheader keys */
  160.  
  161.       if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) ||
  162.            ACCESS_Frame( 2L + 512L )                           )
  163.         goto Fail;
  164.  
  165.       cmap2->language = GET_UShort();
  166.  
  167.       for ( i = 0; i < 256; i++ )
  168.       {
  169.         u = (FT_UShort)( GET_UShort() / 8 );
  170.         cmap2->subHeaderKeys[i] = u;
  171.  
  172.         if ( num_SH < u )
  173.           num_SH = u;
  174.       }
  175.  
  176.       FORGET_Frame();
  177.  
  178.       /* load subheaders */
  179.  
  180.       cmap2->numGlyphId = l = (FT_UShort)(
  181.         ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2 );
  182.  
  183.       if ( ALLOC_ARRAY( cmap2->subHeaders,
  184.                         num_SH + 1,
  185.                         TT_CMap2SubHeader )    ||
  186.            ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
  187.       {
  188.         FREE( cmap2->subHeaderKeys );
  189.         goto Fail;
  190.       }
  191.  
  192.       cmap2sub = cmap2->subHeaders;
  193.  
  194.       for ( i = 0; i <= num_SH; i++ )
  195.       {
  196.         cmap2sub->firstCode     = GET_UShort();
  197.         cmap2sub->entryCount    = GET_UShort();
  198.         cmap2sub->idDelta       = GET_Short();
  199.         /* we apply the location offset immediately */
  200.         cmap2sub->idRangeOffset = (FT_UShort)(
  201.           GET_UShort() - ( num_SH - i ) * 8 - 2 );
  202.  
  203.         cmap2sub++;
  204.       }
  205.  
  206.       FORGET_Frame();
  207.  
  208.       /* load glyph IDs */
  209.  
  210.       if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) ||
  211.            ACCESS_Frame( l * 2L )                           )
  212.       {
  213.         FREE( cmap2->subHeaders );
  214.         FREE( cmap2->subHeaderKeys );
  215.         goto Fail;
  216.       }
  217.  
  218.       for ( i = 0; i < l; i++ )
  219.         cmap2->glyphIdArray[i] = GET_UShort();
  220.  
  221.       FORGET_Frame();
  222.  
  223.       cmap->get_index = code_to_index2;
  224.       cmap->get_next_char = code_to_next2;
  225.       break;
  226.  
  227.     case 4:
  228.       cmap4 = &cmap->c.cmap4;
  229.  
  230.       /* load header */
  231.  
  232.       if ( ACCESS_Frame( 10L ) )
  233.         goto Fail;
  234.  
  235.       cmap4->language      = GET_UShort();
  236.       cmap4->segCountX2    = GET_UShort();
  237.       cmap4->searchRange   = GET_UShort();
  238.       cmap4->entrySelector = GET_UShort();
  239.       cmap4->rangeShift    = GET_UShort();
  240.  
  241.       num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );
  242.  
  243.       FORGET_Frame();
  244.  
  245.       /* load segments */
  246.  
  247.       if ( ALLOC_ARRAY( cmap4->segments,
  248.                         num_Seg,
  249.                         TT_CMap4Segment )           ||
  250.            ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) )
  251.         goto Fail;
  252.  
  253.       segments = cmap4->segments;
  254.  
  255.       for ( i = 0; i < num_Seg; i++ )
  256.         segments[i].endCount      = GET_UShort();
  257.  
  258.       (void)GET_UShort();
  259.  
  260.       for ( i = 0; i < num_Seg; i++ )
  261.         segments[i].startCount    = GET_UShort();
  262.  
  263.       for ( i = 0; i < num_Seg; i++ )
  264.         segments[i].idDelta       = GET_Short();
  265.  
  266.       for ( i = 0; i < num_Seg; i++ )
  267.         segments[i].idRangeOffset = GET_UShort();
  268.  
  269.       FORGET_Frame();
  270.  
  271.       cmap4->numGlyphId = l = (FT_UShort)(
  272.         ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2 );
  273.  
  274.       /* load IDs */
  275.  
  276.       if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) ||
  277.            ACCESS_Frame( l * 2L )                           )
  278.       {
  279.         FREE( cmap4->segments );
  280.         goto Fail;
  281.       }
  282.  
  283.       for ( i = 0; i < l; i++ )
  284.         cmap4->glyphIdArray[i] = GET_UShort();
  285.  
  286.       FORGET_Frame();
  287.  
  288.       cmap4->last_segment = cmap4->segments;
  289.  
  290.       cmap->get_index = code_to_index4;
  291.       cmap->get_next_char = code_to_next4;
  292.       break;
  293.  
  294.     case 6:
  295.       cmap6 = &cmap->c.cmap6;
  296.  
  297.       if ( ACCESS_Frame( 6L ) )
  298.         goto Fail;
  299.  
  300.       cmap6->language   = GET_UShort();
  301.       cmap6->firstCode  = GET_UShort();
  302.       cmap6->entryCount = GET_UShort();
  303.  
  304.       FORGET_Frame();
  305.  
  306.       l = cmap6->entryCount;
  307.  
  308.       if ( ALLOC_ARRAY( cmap6->glyphIdArray, l, FT_Short ) ||
  309.            ACCESS_Frame( l * 2L )                          )
  310.         goto Fail;
  311.  
  312.       for ( i = 0; i < l; i++ )
  313.         cmap6->glyphIdArray[i] = GET_UShort();
  314.  
  315.       FORGET_Frame();
  316.       cmap->get_index = code_to_index6;
  317.       cmap->get_next_char = code_to_next6;
  318.       break;
  319.  
  320.     case 8:
  321.     case 12:
  322.       cmap8_12 = &cmap->c.cmap8_12;
  323.  
  324.       if ( ACCESS_Frame( 8L ) )
  325.         goto Fail;
  326.  
  327.       cmap->length       = GET_ULong();
  328.       cmap8_12->language = GET_ULong();
  329.  
  330.       FORGET_Frame();
  331.  
  332.       if ( cmap->format == 8 )
  333.         if ( FILE_Skip( 8192L ) )
  334.           goto Fail;
  335.  
  336.       if ( READ_ULong( cmap8_12->nGroups ) )
  337.         goto Fail;
  338.  
  339.       n = cmap8_12->nGroups;
  340.  
  341.       if ( ALLOC_ARRAY( cmap8_12->groups, n, TT_CMapGroup ) ||
  342.            ACCESS_Frame( n * 3 * 4L )                       )
  343.         goto Fail;
  344.  
  345.       groups = cmap8_12->groups;
  346.  
  347.       for ( j = 0; j < n; j++ )
  348.       {
  349.         groups[j].startCharCode = GET_ULong();
  350.         groups[j].endCharCode   = GET_ULong();
  351.         groups[j].startGlyphID  = GET_ULong();
  352.       }
  353.  
  354.       FORGET_Frame();
  355.  
  356.       cmap8_12->last_group = cmap8_12->groups;
  357.  
  358.       cmap->get_index = code_to_index8_12;
  359.       cmap->get_next_char = code_to_next8_12;
  360.       break;
  361.  
  362.     case 10:
  363.       cmap10 = &cmap->c.cmap10;
  364.  
  365.       if ( ACCESS_Frame( 16L ) )
  366.         goto Fail;
  367.  
  368.       cmap->length          = GET_ULong();
  369.       cmap10->language      = GET_ULong();
  370.       cmap10->startCharCode = GET_ULong();
  371.       cmap10->numChars      = GET_ULong();
  372.  
  373.       FORGET_Frame();
  374.  
  375.       n = cmap10->numChars;
  376.  
  377.       if ( ALLOC_ARRAY( cmap10->glyphs, n, FT_Short ) ||
  378.            ACCESS_Frame( n * 2L )                     )
  379.         goto Fail;
  380.  
  381.       for ( j = 0; j < n; j++ )
  382.         cmap10->glyphs[j] = GET_UShort();
  383.  
  384.       FORGET_Frame();
  385.       cmap->get_index = code_to_index10;
  386.       cmap->get_next_char = code_to_next10;
  387.       break;
  388.  
  389.     default:   /* corrupt character mapping table */
  390.       return SFNT_Err_Invalid_CharMap_Format;
  391.  
  392.     }
  393.  
  394.     return SFNT_Err_Ok;
  395.  
  396.   Fail:
  397.     TT_CharMap_Free( face, cmap );
  398.     return error;
  399.   }
  400.  
  401.  
  402.   /*************************************************************************/
  403.   /*                                                                       */
  404.   /* <Function>                                                            */
  405.   /*    TT_CharMap_Free                                                    */
  406.   /*                                                                       */
  407.   /* <Description>                                                         */
  408.   /*    Destroys a character mapping table.                                */
  409.   /*                                                                       */
  410.   /* <Input>                                                               */
  411.   /*    face :: A handle to the parent face object.                        */
  412.   /*    cmap :: A handle to a cmap object.                                 */
  413.   /*                                                                       */
  414.   /* <Return>                                                              */
  415.   /*    FreeType error code.  0 means success.                             */
  416.   /*                                                                       */
  417.   FT_LOCAL_DEF FT_Error
  418.   TT_CharMap_Free( TT_Face        face,
  419.                    TT_CMapTable*  cmap )
  420.   {
  421.     FT_Memory  memory;
  422.  
  423.  
  424.     if ( !cmap )
  425.       return SFNT_Err_Ok;
  426.  
  427.     memory = face->root.driver->root.memory;
  428.  
  429.     switch ( cmap->format )
  430.     {
  431.     case 0:
  432.       FREE( cmap->c.cmap0.glyphIdArray );
  433.       break;
  434.  
  435.     case 2:
  436.       FREE( cmap->c.cmap2.subHeaderKeys );
  437.       FREE( cmap->c.cmap2.subHeaders );
  438.       FREE( cmap->c.cmap2.glyphIdArray );
  439.       break;
  440.  
  441.     case 4:
  442.       FREE( cmap->c.cmap4.segments );
  443.       FREE( cmap->c.cmap4.glyphIdArray );
  444.       cmap->c.cmap4.segCountX2 = 0;
  445.       break;
  446.  
  447.     case 6:
  448.       FREE( cmap->c.cmap6.glyphIdArray );
  449.       cmap->c.cmap6.entryCount = 0;
  450.       break;
  451.  
  452.     case 8:
  453.     case 12:
  454.       FREE( cmap->c.cmap8_12.groups );
  455.       cmap->c.cmap8_12.nGroups = 0;
  456.       break;
  457.  
  458.     case 10:
  459.       FREE( cmap->c.cmap10.glyphs );
  460.       cmap->c.cmap10.numChars = 0;
  461.       break;
  462.  
  463.     default:
  464.       /* invalid table format, do nothing */
  465.       ;
  466.     }
  467.  
  468.     cmap->loaded = FALSE;
  469.     return SFNT_Err_Ok;
  470.   }
  471.  
  472.  
  473.   /*************************************************************************/
  474.   /*                                                                       */
  475.   /* <Function>                                                            */
  476.   /*    code_to_index0                                                     */
  477.   /*                                                                       */
  478.   /* <Description>                                                         */
  479.   /*    Converts the character code into a glyph index.  Uses format 0.    */
  480.   /*    `charCode' must be in the range 0x00-0xFF (otherwise 0 is          */
  481.   /*    returned).                                                         */
  482.   /*                                                                       */
  483.   /* <Input>                                                               */
  484.   /*    charCode :: The wanted character code.                             */
  485.   /*    cmap0    :: A pointer to a cmap table in format 0.                 */
  486.   /*                                                                       */
  487.   /* <Return>                                                              */
  488.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  489.   /*                                                                       */
  490.   FT_CALLBACK_DEF( FT_UInt )
  491.   code_to_index0( TT_CMapTable*  cmap,
  492.                   FT_ULong       charCode )
  493.   {
  494.     TT_CMap0*  cmap0 = &cmap->c.cmap0;
  495.  
  496.  
  497.     return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
  498.   }
  499.  
  500.  
  501.   /*************************************************************************/
  502.   /*                                                                       */
  503.   /* <Function>                                                            */
  504.   /*    code_to_next0                                                      */
  505.   /*                                                                       */
  506.   /* <Description>                                                         */
  507.   /*    Finds the next encoded character after the given one.  Uses        */
  508.   /*    format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0   */
  509.   /*    is returned).                                                      */
  510.   /*                                                                       */
  511.   /* <Input>                                                               */
  512.   /*    charCode :: The wanted character code.                             */
  513.   /*    cmap0    :: A pointer to a cmap table in format 0.                 */
  514.   /*                                                                       */
  515.   /* <Return>                                                              */
  516.   /*    Next char code.  0 if no higher one is encoded.                    */
  517.   /*                                                                       */
  518.   FT_CALLBACK_DEF( FT_ULong )
  519.   code_to_next0( TT_CMapTable*  cmap,
  520.                  FT_ULong       charCode )
  521.   {
  522.     TT_CMap0*  cmap0 = &cmap->c.cmap0;
  523.  
  524.  
  525.     while ( ++charCode <= 0xFF )
  526.       if ( cmap0->glyphIdArray[charCode] )
  527.         return ( charCode );
  528.     return ( 0 );
  529.   }
  530.  
  531.  
  532.   /*************************************************************************/
  533.   /*                                                                       */
  534.   /* <Function>                                                            */
  535.   /*    code_to_index2                                                     */
  536.   /*                                                                       */
  537.   /* <Description>                                                         */
  538.   /*    Converts the character code into a glyph index.  Uses format 2.    */
  539.   /*                                                                       */
  540.   /* <Input>                                                               */
  541.   /*    charCode :: The wanted character code.                             */
  542.   /*    cmap2    :: A pointer to a cmap table in format 2.                 */
  543.   /*                                                                       */
  544.   /* <Return>                                                              */
  545.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  546.   /*                                                                       */
  547.   FT_CALLBACK_DEF( FT_UInt )
  548.   code_to_index2( TT_CMapTable*  cmap,
  549.                   FT_ULong       charCode )
  550.   {
  551.     FT_UInt             result, index1, offset;
  552.     FT_UInt             char_lo;
  553.     FT_ULong            char_hi;
  554.     TT_CMap2SubHeader*  sh2;
  555.     TT_CMap2*           cmap2;
  556.  
  557.  
  558.     cmap2   = &cmap->c.cmap2;
  559.     result  = 0;
  560.     char_lo = (FT_UInt)( charCode & 0xFF );
  561.     char_hi = charCode >> 8;
  562.  
  563.     if ( char_hi == 0 )
  564.     {
  565.       /* an 8-bit character code -- we use the subHeader 0 in this case */
  566.       /* to test whether the character code is in the charmap           */
  567.       index1 = cmap2->subHeaderKeys[char_lo];
  568.       if ( index1 != 0 )
  569.         return 0;
  570.     }
  571.     else
  572.     {
  573.       /* a 16-bit character code */
  574.       index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
  575.       if ( index1 == 0 )
  576.         return 0;
  577.     }
  578.  
  579.     sh2      = cmap2->subHeaders + index1;
  580.     char_lo -= sh2->firstCode;
  581.  
  582.     if ( char_lo < (FT_UInt)sh2->entryCount )
  583.     {
  584.       offset = sh2->idRangeOffset / 2 + char_lo;
  585.       if ( offset < (FT_UInt)cmap2->numGlyphId )
  586.       {
  587.         result = cmap2->glyphIdArray[offset];
  588.         if ( result )
  589.           result = ( result + sh2->idDelta ) & 0xFFFF;
  590.       }
  591.     }
  592.  
  593.     return result;
  594.   }
  595.  
  596.  
  597.   /*************************************************************************/
  598.   /*                                                                       */
  599.   /* <Function>                                                            */
  600.   /*    code_to_next2                                                      */
  601.   /*                                                                       */
  602.   /* <Description>                                                         */
  603.   /*    Find the next encoded character.  Uses format 2.                   */
  604.   /*                                                                       */
  605.   /* <Input>                                                               */
  606.   /*    charCode :: The wanted character code.                             */
  607.   /*    cmap2    :: A pointer to a cmap table in format 2.                 */
  608.   /*                                                                       */
  609.   /* <Return>                                                              */
  610.   /*    Next encoded character.  0 if none exists.                         */
  611.   /*                                                                       */
  612.   FT_CALLBACK_DEF( FT_ULong )
  613.   code_to_next2( TT_CMapTable*  cmap,
  614.                  FT_ULong       charCode )
  615.   {
  616.     FT_UInt             index1, offset;
  617.     FT_UInt             char_lo;
  618.     FT_ULong            char_hi;
  619.     TT_CMap2SubHeader*  sh2;
  620.     TT_CMap2*           cmap2;
  621.  
  622.  
  623.     cmap2 = &cmap->c.cmap2;
  624.     charCode++;
  625.  
  626.     /*
  627.      * This is relatively simplistic -- look for a subHeader containing
  628.      * glyphs and then walk to the first glyph in that subHeader.
  629.      */
  630.     while ( charCode < 0x10000 )
  631.     {
  632.       char_lo = (FT_UInt)( charCode & 0xFF );
  633.       char_hi = charCode >> 8;
  634.   
  635.       if ( char_hi == 0 )
  636.       {
  637.         /* an 8-bit character code -- we use the subHeader 0 in this case */
  638.         /* to test whether the character code is in the charmap           */
  639.         index1 = cmap2->subHeaderKeys[char_lo];
  640.         if ( index1 != 0 )
  641.         {
  642.           charCode++;
  643.           continue;
  644.         }
  645.       }
  646.       else
  647.       {
  648.         /* a 16-bit character code */
  649.         index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
  650.         if ( index1 == 0 )
  651.         {
  652.           charCode = ( char_hi + 1 ) << 8;
  653.           continue;
  654.         }
  655.       }
  656.   
  657.       sh2      = cmap2->subHeaders + index1;
  658.       char_lo -= sh2->firstCode;
  659.   
  660.       if ( char_lo > (FT_UInt)sh2->entryCount )
  661.       {
  662.         charCode = ( char_hi + 1 ) << 8;
  663.         continue;
  664.       }
  665.       
  666.       offset = sh2->idRangeOffset / 2 + char_lo;
  667.       if ( offset >= (FT_UInt)cmap2->numGlyphId ||
  668.            cmap2->glyphIdArray[offset] == 0     )
  669.       {
  670.         charCode++;
  671.         continue;
  672.       }
  673.       
  674.       return charCode;
  675.     }
  676.     return 0;
  677.   }
  678.  
  679.  
  680.   /*************************************************************************/
  681.   /*                                                                       */
  682.   /* <Function>                                                            */
  683.   /*    code_to_index4                                                     */
  684.   /*                                                                       */
  685.   /* <Description>                                                         */
  686.   /*    Converts the character code into a glyph index.  Uses format 4.    */
  687.   /*                                                                       */
  688.   /* <Input>                                                               */
  689.   /*    charCode :: The wanted character code.                             */
  690.   /*    cmap4    :: A pointer to a cmap table in format 4.                 */
  691.   /*                                                                       */
  692.   /* <Return>                                                              */
  693.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  694.   /*                                                                       */
  695.   FT_CALLBACK_DEF( FT_UInt )
  696.   code_to_index4( TT_CMapTable*  cmap,
  697.                   FT_ULong       charCode )
  698.   {
  699.     FT_UInt          result, index1, segCount;
  700.     TT_CMap4*        cmap4;
  701.     TT_CMap4Segment  *seg4, *limit;
  702.  
  703.  
  704.     cmap4    = &cmap->c.cmap4;
  705.     result   = 0;
  706.     segCount = cmap4->segCountX2 / 2;
  707.     limit    = cmap4->segments + segCount;
  708.  
  709.     /* first, check against the last used segment */
  710.  
  711.     seg4 = cmap4->last_segment;
  712.  
  713.     /* the following is equivalent to performing two tests, as in         */
  714.     /*                                                                    */
  715.     /*  if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
  716.     /*                                                                    */
  717.     /* This is a bit strange, but it is faster, and the idea behind the   */
  718.     /* cache is to significantly speed up charcode to glyph index         */
  719.     /* conversion.                                                        */
  720.  
  721.     if ( (FT_ULong)( charCode       - seg4->startCount ) <
  722.          (FT_ULong)( seg4->endCount - seg4->startCount ) )
  723.       goto Found1;
  724.  
  725.     for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
  726.     {
  727.       /* the ranges are sorted in increasing order.  If we are out of */
  728.       /* the range here, the char code isn't in the charmap, so exit. */
  729.  
  730.       if ( charCode > (FT_UInt)seg4->endCount )
  731.         continue;
  732.  
  733.       if ( charCode >= (FT_UInt)seg4->startCount )
  734.         goto Found;
  735.     }
  736.     return 0;
  737.  
  738.   Found:
  739.     cmap4->last_segment = seg4;
  740.  
  741.   Found1:
  742.     /* if the idRangeOffset is 0, we can compute the glyph index */
  743.     /* directly                                                  */
  744.  
  745.     if ( seg4->idRangeOffset == 0 )
  746.       result = ( charCode + seg4->idDelta ) & 0xFFFF;
  747.     else
  748.     {
  749.       /* otherwise, we must use the glyphIdArray to do it */
  750.       index1 = (FT_UInt)( seg4->idRangeOffset / 2
  751.                           + ( charCode - seg4->startCount )
  752.                           + ( seg4 - cmap4->segments )
  753.                           - segCount );
  754.  
  755.       if ( index1 < (FT_UInt)cmap4->numGlyphId &&
  756.            cmap4->glyphIdArray[index1] != 0    )
  757.         result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF;
  758.     }
  759.  
  760.     return result;
  761.   }
  762.  
  763.  
  764.   /*************************************************************************/
  765.   /*                                                                       */
  766.   /* <Function>                                                            */
  767.   /*    code_to_next4                                                      */
  768.   /*                                                                       */
  769.   /* <Description>                                                         */
  770.   /*    Find the next encoded character.  Uses format 4.                   */
  771.   /*                                                                       */
  772.   /* <Input>                                                               */
  773.   /*    charCode :: The wanted character code.                             */
  774.   /*    cmap     :: A pointer to a cmap table in format 4.                 */
  775.   /*                                                                       */
  776.   /* <Return>                                                              */
  777.   /*    Next encoded character.  0 if none exists.                         */
  778.   /*                                                                       */
  779.   FT_CALLBACK_DEF( FT_ULong )
  780.   code_to_next4( TT_CMapTable*  cmap,
  781.                  FT_ULong       charCode )
  782.   {
  783.     FT_UInt          index1, segCount;
  784.     TT_CMap4*        cmap4;
  785.     TT_CMap4Segment  *seg4, *limit;
  786.  
  787.  
  788.     cmap4    = &cmap->c.cmap4;
  789.     segCount = cmap4->segCountX2 / 2;
  790.     limit    = cmap4->segments + segCount;
  791.  
  792.     charCode++;
  793.  
  794.     for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
  795.     {
  796.       /* The ranges are sorted in increasing order.  If we are out of */
  797.       /* the range here, the char code isn't in the charmap, so exit. */
  798.  
  799.       if ( charCode <= (FT_UInt)seg4->endCount )
  800.         goto Found;
  801.     }
  802.     return 0;
  803.  
  804.   Found:
  805.     if ( charCode < (FT_ULong) seg4->startCount )
  806.       charCode = seg4->startCount;
  807.  
  808.     /* if the idRangeOffset is 0, all chars in the map exist */
  809.  
  810.     if ( seg4->idRangeOffset == 0 )
  811.       return ( charCode );
  812.     
  813.     while ( charCode <= (FT_UInt) seg4->endCount )
  814.     {
  815.       /* otherwise, we must use the glyphIdArray to do it */
  816.       index1 = (FT_UInt)( seg4->idRangeOffset / 2
  817.                           + ( charCode - seg4->startCount )
  818.                           + ( seg4 - cmap4->segments )
  819.                           - segCount );
  820.  
  821.       if ( index1 < (FT_UInt)cmap4->numGlyphId &&
  822.            cmap4->glyphIdArray[index1] != 0    )
  823.         return ( charCode );
  824.       charCode++;
  825.     }
  826.  
  827.     return 0;
  828.   }
  829.  
  830.  
  831.   /*************************************************************************/
  832.   /*                                                                       */
  833.   /* <Function>                                                            */
  834.   /*    code_to_index6                                                     */
  835.   /*                                                                       */
  836.   /* <Description>                                                         */
  837.   /*    Converts the character code into a glyph index.  Uses format 6.    */
  838.   /*                                                                       */
  839.   /* <Input>                                                               */
  840.   /*    charCode :: The wanted character code.                             */
  841.   /*    cmap6    :: A pointer to a cmap table in format 6.                 */
  842.   /*                                                                       */
  843.   /* <Return>                                                              */
  844.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  845.   /*                                                                       */
  846.   FT_CALLBACK_DEF( FT_UInt )
  847.   code_to_index6( TT_CMapTable*  cmap,
  848.                   FT_ULong       charCode )
  849.   {
  850.     TT_CMap6*  cmap6;
  851.     FT_UInt    result = 0;
  852.  
  853.  
  854.     cmap6     = &cmap->c.cmap6;
  855.     charCode -= cmap6->firstCode;
  856.  
  857.     if ( charCode < (FT_UInt)cmap6->entryCount )
  858.       result = cmap6->glyphIdArray[charCode];
  859.  
  860.     return result;
  861.   }
  862.  
  863.  
  864.   /*************************************************************************/
  865.   /*                                                                       */
  866.   /* <Function>                                                            */
  867.   /*    code_to_next6                                                      */
  868.   /*                                                                       */
  869.   /* <Description>                                                         */
  870.   /*    Find the next encoded character.  Uses format 6.                   */
  871.   /*                                                                       */
  872.   /* <Input>                                                               */
  873.   /*    charCode :: The wanted character code.                             */
  874.   /*    cmap     :: A pointer to a cmap table in format 6.                 */
  875.   /*                                                                       */
  876.   /* <Return>                                                              */
  877.   /*    Next encoded character.  0 if none exists.                         */
  878.   /*                                                                       */
  879.   FT_CALLBACK_DEF( FT_ULong )
  880.   code_to_next6( TT_CMapTable*  cmap,
  881.                  FT_ULong       charCode )
  882.   {
  883.     TT_CMap6*  cmap6;
  884.  
  885.  
  886.     charCode++;
  887.     
  888.     cmap6 = &cmap->c.cmap6;
  889.     
  890.     if ( charCode < (FT_ULong) cmap6->firstCode )
  891.       charCode = cmap6->firstCode;
  892.     
  893.     charCode -= cmap6->firstCode;
  894.  
  895.     while ( charCode < (FT_UInt)cmap6->entryCount )
  896.     {
  897.       if ( cmap6->glyphIdArray[charCode] != 0 )
  898.         return charCode + cmap6->firstCode;
  899.       charCode++;
  900.     }
  901.  
  902.     return 0;
  903.   }
  904.  
  905.  
  906.   /*************************************************************************/
  907.   /*                                                                       */
  908.   /* <Function>                                                            */
  909.   /*    code_to_index8_12                                                  */
  910.   /*                                                                       */
  911.   /* <Description>                                                         */
  912.   /*    Converts the (possibly 32bit) character code into a glyph index.   */
  913.   /*    Uses format 8 or 12.                                               */
  914.   /*                                                                       */
  915.   /* <Input>                                                               */
  916.   /*    charCode :: The wanted character code.                             */
  917.   /*    cmap8_12 :: A pointer to a cmap table in format 8 or 12.           */
  918.   /*                                                                       */
  919.   /* <Return>                                                              */
  920.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  921.   /*                                                                       */
  922.   FT_CALLBACK_DEF( FT_UInt )
  923.   code_to_index8_12( TT_CMapTable*  cmap,
  924.                      FT_ULong       charCode )
  925.   {
  926.     TT_CMap8_12*  cmap8_12;
  927.     TT_CMapGroup  *group, *limit;
  928.  
  929.  
  930.     cmap8_12 = &cmap->c.cmap8_12;
  931.     limit    = cmap8_12->groups + cmap8_12->nGroups;
  932.  
  933.     /* first, check against the last used group */
  934.  
  935.     group = cmap8_12->last_group;
  936.  
  937.     /* the following is equivalent to performing two tests, as in       */
  938.     /*                                                                  */
  939.     /*  if ( charCode >= group->startCharCode &&                        */
  940.     /*       charCode <= group->endCharCode   )                         */
  941.     /*                                                                  */
  942.     /* This is a bit strange, but it is faster, and the idea behind the */
  943.     /* cache is to significantly speed up charcode to glyph index       */
  944.     /* conversion.                                                      */
  945.  
  946.     if ( (FT_ULong)( charCode           - group->startCharCode ) <
  947.          (FT_ULong)( group->endCharCode - group->startCharCode ) )
  948.       goto Found1;
  949.  
  950.     for ( group = cmap8_12->groups; group < limit; group++ )
  951.     {
  952.       /* the ranges are sorted in increasing order.  If we are out of */
  953.       /* the range here, the char code isn't in the charmap, so exit. */
  954.  
  955.       if ( charCode > group->endCharCode )
  956.         continue;
  957.  
  958.       if ( charCode >= group->startCharCode )
  959.         goto Found;
  960.     }
  961.     return 0;
  962.  
  963.   Found:
  964.     cmap8_12->last_group = group;
  965.  
  966.   Found1:
  967.     return group->startGlyphID + (FT_UInt)( charCode - group->startCharCode );
  968.   }
  969.  
  970.  
  971.   /*************************************************************************/
  972.   /*                                                                       */
  973.   /* <Function>                                                            */
  974.   /*    code_to_next8_12                                                   */
  975.   /*                                                                       */
  976.   /* <Description>                                                         */
  977.   /*    Find the next encoded character.  Uses format 8 or 12.             */
  978.   /*                                                                       */
  979.   /* <Input>                                                               */
  980.   /*    charCode :: The wanted character code.                             */
  981.   /*    cmap     :: A pointer to a cmap table in format 8 or 12.           */
  982.   /*                                                                       */
  983.   /* <Return>                                                              */
  984.   /*    Next encoded character.  0 if none exists.                         */
  985.   /*                                                                       */
  986.   FT_CALLBACK_DEF( FT_ULong )
  987.   code_to_next8_12( TT_CMapTable*  cmap,
  988.                     FT_ULong       charCode )
  989.   {
  990.     TT_CMap8_12*  cmap8_12;
  991.     TT_CMapGroup  *group, *limit;
  992.  
  993.  
  994.     charCode++;
  995.     cmap8_12 = &cmap->c.cmap8_12;
  996.     limit    = cmap8_12->groups + cmap8_12->nGroups;
  997.  
  998.     for ( group = cmap8_12->groups; group < limit; group++ )
  999.     {
  1000.       /* the ranges are sorted in increasing order.  If we are out of */
  1001.       /* the range here, the char code isn't in the charmap, so exit. */
  1002.  
  1003.       if ( charCode <= group->endCharCode )
  1004.         goto Found;
  1005.     }
  1006.     return 0;
  1007.  
  1008.   Found:
  1009.     if ( charCode < group->startCharCode )
  1010.       charCode = group->startCharCode;
  1011.     
  1012.     return charCode;
  1013.   }
  1014.  
  1015.  
  1016.   /*************************************************************************/
  1017.   /*                                                                       */
  1018.   /* <Function>                                                            */
  1019.   /*    code_to_index10                                                    */
  1020.   /*                                                                       */
  1021.   /* <Description>                                                         */
  1022.   /*    Converts the (possibly 32bit) character code into a glyph index.   */
  1023.   /*    Uses format 10.                                                    */
  1024.   /*                                                                       */
  1025.   /* <Input>                                                               */
  1026.   /*    charCode :: The wanted character code.                             */
  1027.   /*    cmap10   :: A pointer to a cmap table in format 10.                */
  1028.   /*                                                                       */
  1029.   /* <Return>                                                              */
  1030.   /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
  1031.   /*                                                                       */
  1032.   FT_CALLBACK_DEF( FT_UInt )
  1033.   code_to_index10( TT_CMapTable*  cmap,
  1034.                    FT_ULong       charCode )
  1035.   {
  1036.     TT_CMap10*  cmap10;
  1037.     FT_UInt     result = 0;
  1038.  
  1039.  
  1040.     cmap10    = &cmap->c.cmap10;
  1041.     charCode -= cmap10->startCharCode;
  1042.  
  1043.     /* the overflow trick for comparison works here also since the number */
  1044.     /* of glyphs (even if numChars is specified as ULong in the specs) in */
  1045.     /* an OpenType font is limited to 64k                                 */
  1046.  
  1047.     if ( charCode < cmap10->numChars )
  1048.       result = cmap10->glyphs[charCode];
  1049.  
  1050.     return result;
  1051.   }
  1052.  
  1053.  
  1054.   /*************************************************************************/
  1055.   /*                                                                       */
  1056.   /* <Function>                                                            */
  1057.   /*    code_to_next10                                                     */
  1058.   /*                                                                       */
  1059.   /* <Description>                                                         */
  1060.   /*    Find the next encoded character.  Uses format 10.                  */
  1061.   /*                                                                       */
  1062.   /* <Input>                                                               */
  1063.   /*    charCode :: The wanted character code.                             */
  1064.   /*    cmap     :: A pointer to a cmap table in format 10.                */
  1065.   /*                                                                       */
  1066.   /* <Return>                                                              */
  1067.   /*    Next encoded character.  0 if none exists.                         */
  1068.   /*                                                                       */
  1069.   FT_CALLBACK_DEF( FT_ULong )
  1070.   code_to_next10( TT_CMapTable*  cmap,
  1071.                   FT_ULong       charCode )
  1072.   {
  1073.     TT_CMap10*  cmap10;
  1074.  
  1075.  
  1076.     charCode++;
  1077.     cmap10 = &cmap->c.cmap10;
  1078.     
  1079.     if ( charCode < cmap10->startCharCode )
  1080.       charCode = cmap10->startCharCode;
  1081.     
  1082.     charCode -= cmap10->startCharCode;
  1083.  
  1084.     /* the overflow trick for comparison works here also since the number */
  1085.     /* of glyphs (even if numChars is specified as ULong in the specs) in */
  1086.     /* an OpenType font is limited to 64k                                 */
  1087.  
  1088.     while ( charCode < cmap10->numChars )
  1089.     {
  1090.       if ( cmap10->glyphs[charCode] )
  1091.         return ( charCode + cmap10->startCharCode );
  1092.       charCode++;
  1093.     }
  1094.  
  1095.     return 0;
  1096.   }
  1097.  
  1098.  
  1099. /* END */
  1100.